package top.laoshuzi.rxmvp;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class RxMvpClassAction extends AnAction {


    private Project project;
    private VirtualFile virtualFile;

    private Dialog dialog;

    private String packagebase = "";
    private String packagename = "";

    private ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("取消")) {
            } else {

            }
        }
    };

    @Override
    public void actionPerformed(AnActionEvent event) {
        project = event.getData(PlatformDataKeys.PROJECT);
        virtualFile = event.getData(CommonDataKeys.VIRTUAL_FILE);
        if (project != null && virtualFile != null) {
            initData();
            initView();
        }

    }


    private void initData() {
        if (!virtualFile.isDirectory())
            virtualFile = virtualFile.getParent();
        packagebase = readPackageBase();
        packagename = readPackageName();
    }

    private void initView() {
        dialog = new Dialog(project);
        dialog.setClickListener(new Dialog.OnClickListener() {
            @Override
            public void onOkClick() {
                createFiles(CodeType.Contract);
                createFiles(CodeType.Presenter);
                createFiles(CodeType.Model);
                createFiles(CodeType.IModel);
                Messages.showInfoMessage(project, "生成完毕", "提示");
            }

            @Override
            public void onCancelClick() {

            }
        });
        dialog.show();
    }

    /**
     * 读取包基本名称
     *
     * @return
     */
    private String readPackageBase() {

        String manifestPath = readAndroidManifestPath();
        if (manifestPath != null) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder db = dbf.newDocumentBuilder();
                Document doc = db.parse(manifestPath);

                NodeList dogList = doc.getElementsByTagName("manifest");
                for (int i = 0; i < dogList.getLength(); i++) {
                    Node dog = dogList.item(i);
                    Element elem = (Element) dog;
                    return elem.getAttribute("package");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 读取包名称
     *
     * @return
     */
    private String readPackageName() {
        String path = virtualFile.getPath();
        path = path.replace("/", ".");
        return StringUtil.substringAfter(path, packagebase);
    }

    private String readAndroidManifestPath() {

        VirtualFile temp = virtualFile;
        do {
            File file = new File(temp.getPath(), "AndroidManifest.xml");
            if (file.exists())
                return file.getPath();
            else
                temp = temp.getParent();
        } while (temp == null || !project.getBasePath().equals(temp.getPath()));

        return null;
    }


    /**
     * 创建文件
     */
    private void createFiles(CodeType codeType) {

        String content = "";
        String filename = "";

        switch (codeType) {
            case Contract:
                filename = "TemplateContract.txt";
                content = ReadFile(filename);
                content = dealFileTitle(content);
                content = dealContract(content);
                writetoFile(content, virtualFile.getPath() + "/contract", dialog.getName() + "Contract.java");
                break;
            case Presenter:
                filename = "TemplatePresenter.txt";
                content = ReadFile(filename);
                content = dealFileTitle(content);
                content = dealPresenter(content);
                writetoFile(content, virtualFile.getPath() + "/presenter", dialog.getName() + "Presenter.java");
                break;
            case Model:
                filename = "TemplateModel.txt";
                content = ReadFile(filename);
                content = dealFileTitle(content);
                content = dealModel(content);
                writetoFile(content, virtualFile.getPath() + "/model", dialog.getName() + "Model.java");
                break;
            case IModel:
                filename = "TemplateIModel.txt";
                content = ReadFile(filename);
                content = dealFileTitle(content);
                content = dealIModel(content);
                writetoFile(content, virtualFile.getPath() + "/model", "I" + dialog.getName() + "Model.java");
                break;
        }

    }

    /**
     * 处理FileTitle
     *
     * @param content
     */
    private String dealFileTitle(String content) {
        content = content.replace("$author", dialog.getAuthor());
        content = content.replace("$date", getNowDateShort());
        return content;
    }

    /**
     * 处理Contract
     *
     * @param content
     * @return
     */
    private String dealContract(String content) {
        content = content.replace("$name", dialog.getName());
        content = content.replace("$packagename", packagebase + packagename + ".contract");
        return content;
    }


    /**
     * 处理Presenter
     *
     * @param content
     * @return
     */
    private String dealPresenter(String content) {
        content = content.replace("$name_low", dialog.getName().toLowerCase());
        content = content.replace("$name", dialog.getName());
        content = content.replace("$packagename", packagebase + packagename + ".presenter");
        content = content.replace("$packagepath", packagebase + packagename);
        return content;
    }

    /**
     * 处理Model
     *
     * @return
     */
    private String dealModel(String content) {
        content = content.replace("$name", dialog.getName());
        content = content.replace("$packagename", packagebase + packagename + ".model");
        return content;
    }

    /**
     * 处理IModel
     *
     * @param content
     * @return
     */
    private String dealIModel(String content) {
        content = content.replace("$name", dialog.getName());
        content = content.replace("$packagename", packagebase + packagename + ".model");
        return content;
    }


    private String getNowDateShort() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    private String ReadFile(String filename) {
        InputStream in = null;
        in = this.getClass().getResourceAsStream("/top/laoshuzi/rxmvp/template/" + filename);
        String content = "";
        try {
            content = new String(readStream(in));
        } catch (Exception e) {
        }
        return content;
    }

    private void writetoFile(String content, String filepath, String filename) {
        try {
            File floder = new File(filepath);
            // if file doesnt exists, then create it
            if (!floder.exists()) {
                floder.mkdirs();
            }
            File file = new File(filepath + "/" + filename);
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private byte[] readStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        try {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
//                System.out.println(new String(buffer));
            }

        } catch (IOException e) {
        } finally {
            outSteam.close();
            inStream.close();
        }
        return outSteam.toByteArray();
    }


    private enum CodeType {
        Contract, Model, IModel, Presenter
    }


}
